home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
DB_CLIPP
/
0277.ZIP
/
USQ2.C
< prev
next >
Wrap
Text File
|
1986-02-28
|
20KB
|
933 lines
static char *sccsid = "@(#)usq2.c 1.9u (UCF) 13/02/86";
/*
* THIS IS THE SOURCE CODE FOR USQ2.C.
*
* usq.c - CP/M compatible multi-disk file unsqueezer utility
*
*/
/* modified by J. Chappell 02-02-84 to check if ferror occurred on write
02-07-84 to accept wildcards in filenames
07-01-86 to match sq2.c (Ark - v1.9u)
13-02-86 for CP/M86 and MSC
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef CPMC86
#define strupr upper
#endif
#ifdef MSDC86
#include <time.h>
#endif
#ifdef MSDMSC
#include <time.h>
#include <dos.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#define BWRITE O_RDWR|O_CREAT|O_BINARY
#define BPERMS S_IREAD|S_IWRITE
#define BREAD O_RDONLY|O_BINARY
#endif
#define VERSION "1.9u 14-02-86"
#define TRUE 1
#define FALSE 0
#define ERROR (-1)
#define PATHLEN 64 /* Number of characters allowed in pathname */
#define OK 0
#define RECOGNIZE 0xFF76 /* unlikely pattern */
#define DLE 0x90 /* repeat byte flag */
#define SPEOF 256 /* special endfile token */
#define NUMVALS 257 /* 256 data values plus SPEOF*/
#define LARGE 30000
typedef int INT;
typedef unsigned UNSIGNED;
struct _sqleaf { /* Decoding tree */
INT _children[2]; /* left, right */
};
struct _sqleaf Dnode[NUMVALS - 1];
INT Bpos; /* last bit position read */
INT Curin; /* last byte value read */
INT Repct; /* Number of times to return value */
INT Value; /* current byte value or EOF */
INT MakeLCPathname=TRUE; /* translate pathname to lc if all caps */
INT Nlmode=FALSE; /* zap cr's if true */
INT Inbackground = FALSE;
INT getcr(), getuhuff(), portgetw();
/* new globals for version 1.9u
---------------------------- */
int dcount = 0;
int fcount = 0;
long free_space = 0L;
long old_date;
INT bkup_id = 0;
INT span_cnt = 0;
char src_drv[20];
char tgt_fils[PATHLEN+2];
unsigned char outfile[PATHLEN+2]; /* output file spec. */
unsigned char infile[PATHLEN+2];
FILE *in, *out;
char tgt_path[PATHLEN+2], src_path[PATHLEN+2], src_name[16];
char origname[PATHLEN]; /* Original file name without drive */
char *first, *next;
#define SPAN_CHR 0xff /* marks incomplete restore/file */
#define FIN_CHR 0x00 /* marks last disk/last segment */
/* structure of SQZID.@@@ */
struct bki {
unsigned char bk_fflag; /* FF=middle disk 00=last disk */
int bk_seqn; /* disk sequence number */
long bk_date; /* backup date in long format - seconds since 01.01.70 */
char bk_spare[121];
} bkid;
/* structure of SQUEEZED file header */
struct sqh {
unsigned char sq_fflag; /* FF=incomplete 00=last segment */
int sq_span; /* span count */
int sq_nulo;
char sq_path[65]; /* path + filename */
char sq_spare[58]; /* spare */
} sqid;
FILE *fopen();
main(argc, argv)
unsigned char *argv[];
{
char *ptr;
int errorstat;
if(argc != 3)
usage();
/* get the source drive - limited to A or B */
strcpy(src_drv, argv[1]);
strupr(src_drv);
if(src_drv[0] > 'B' || src_drv[0] < 'A' || src_drv[1] != ':' || hasbad(src_drv))
abort("\007usq2: source drive must be drive A: or drive B:");
/* get the target files and check that they are not the same drive */
strcpy(tgt_fils, argv[2]);
strupr(tgt_fils);
if(strchr(tgt_fils,':') != NULL && (src_drv[0] == tgt_fils[0]))
abort("\007usq2: source and destination drives are the same!\n\n");
/* convert all '/' to '\' */
for(ptr = tgt_fils; *ptr; ptr++)
if(*ptr == '/')
*ptr = '\\';
/* now isolate the path */
get_path(tgt_fils, tgt_path);
/* now make the path, if neccesary, on the target */
if(mak_path(tgt_fils) == EOF)
{
fprintf(stderr, "\007usq2: can't make path for %s\n", tgt_fils);
exit(1);
}
errorstat=0;
for(;;)
{
new_disk();
if(first == NULL)
{
if(bkid.bk_fflag == '\0')
break;
else
continue;
}
do
{
strcpy(src_name, src_drv);
strcat(src_name,next);
errorstat |= squeeze();
next = next + strlen(next) + 1;
}
while(*next != '\0');
if(!haswild(tgt_fils) && sqid.sq_fflag == '\0')
break;
if(bkid.bk_fflag == '\0')
break;
}
exit(errorstat != 0);
}
/* log in a new disk */
new_disk()
{
int bk;
char src[20], *d_ptr;
char *filedir();
if(++bkup_id != 1 && first != NULL)
free(first);
if(sqid.sq_fflag == SPAN_CHR && bkup_id != 1)
{
fclose(in);
}
for(;;)
{
fprintf(stderr,"\n\n%cInsert restore diskette %02d in drive %s\n",'\007',bkup_id, src_drv);
fprintf(stderr,"Strike any key when ready... ");
bdos(1,0);
dsk_reset(src_drv);
if((bk = get_bkupid(src_drv)) < 0)
{
fprintf(stderr,"\n\n%cERROR - not a restore diskette in drive %s\n",'\007', src_drv);
fprintf(stderr,"Strike any key when ready... ");
bdos(1,0);
continue;
}
if(dcount == 0)
old_date = bkid.bk_date;
else
if(old_date != bkid.bk_date)
{
fprintf(stderr,"\n\n%cERROR - different backup date on restore diskette in drive %s \n",'\007', src_drv);
fprintf(stderr,"Strike any key when ready... ");
bdos(1,0);
continue;
}
if(bk != bkup_id)
{
fprintf(stderr,"\n\n%cRestore diskette %02d in drive %s is out of sequence\n",'\007',bk, src_drv);
fprintf(stderr,"Strike any key when ready... ");
bdos(1,0);
if(dcount == 0)
{
bkup_id = bk;
}
else
continue;
}
fprintf(stderr,"\n\n*** Unsqueezing files from diskette %02d ***\n",bkup_id);
strcpy(src,src_drv);
if((d_ptr = strrchr(tgt_fils, '\\')) != NULL)
strcat(src, ++d_ptr);
else if((d_ptr = strrchr(tgt_fils, '/')) != NULL)
strcat(src, ++d_ptr);
else if((d_ptr = strrchr(tgt_fils, ':')) != NULL)
strcat(src, ++d_ptr);
else
strcat(src, tgt_fils);
first = filedir(src,0);
next = first;
dcount++;
break;
}
/* skip first entry - SQZID.@@@ */
if(strcmp(next, "SQZID.@@@") == 0)
next = next + strlen(next) + 1;
if(sqid.sq_fflag == SPAN_CHR && bkup_id != 1)
{
if((in=fopen(src_name, "rb"))==NULL)
{
fprintf(stderr, "\n\n%cERROR - can't open %s - SEQUENCE\n", '\007',src_name);
exit(1);
}
/* get squeeze "RESTORE" header and make sure we have right part of file */
get_sqhdr();
if(sqid.sq_span != ++fcount)
{
fclose(in);
fprintf(stderr,"\n\n%cERROR - file %s out of sequence\n\n",'\007',src_name);
exit(1);
}
/* now check that we have the same path */
strupr(sqid.sq_path);
get_path(sqid.sq_path,src_path);
if((d_ptr = strchr(tgt_path, ':')) != NULL)
d_ptr++;
else
d_ptr = &tgt_path[0];
if(strcmp(src_path, d_ptr) != 0)
{
fclose(in);
fprintf(stderr,"\n\n%cERROR - file %s out of sequence\n\n",'\007',src_name);
exit(1);
}
if (!Inbackground)
fprintf(stderr, "usq2: %s -> %s\n",src_name,origname);
}
return(TRUE);
}
get_bkupid(drive)
char *drive;
{
char filespec[16];
int fd;
strcpy(filespec,drive);
strcat(filespec,"SQZID.@@@");
if((fd = open(filespec,BREAD)) < 0)
return(fd);
read(fd,&bkid,sizeof(bkid));
close(fd);
return( (int) (bkid.bk_seqn));
}
/*
The following code is primarily from typesq.c and utr.c. Typesq
is a modification of USQ by Dick Greenlaw. Those modifications (usq
to typesq) were made by Bob Mathias, I am responsible for the butchery
done to make it work with cat.
*/
squeeze()
{
register INT i, c;
register unsigned char *p;
register INT numnodes; /* size of decoding tree */
register UNSIGNED crc;
UNSIGNED filecrc;
char *d_ptr;
init_cr();
init_huff();
crc=0;
fcount = 0;
if((in=fopen(src_name, "rb"))==NULL)
{
fprintf(stderr, "\007usq2: can't open %s\n", src_name);
return ERROR;
}
/* get squeeze "RESTORE" header and make sure we have first part of file */
get_sqhdr();
if(sqid.sq_span != 0)
{
fclose(in);
fprintf(stderr,"\n\n%cERROR - file %s out of sequence\n\n",'\007',src_name);
exit(1);
}
/* now check that we have the same path */
strupr(sqid.sq_path);
get_path(sqid.sq_path,src_path);
if((d_ptr = strchr(tgt_path, ':')) != NULL)
d_ptr++;
else
d_ptr = &tgt_path[0];
if(strcmp(src_path, d_ptr) != 0)
{
fclose(in);
return(OK);
}
/* now process "SQUEEZE" header */
if(portgetw(in) != (INT) RECOGNIZE) /* Process header */
{
fprintf(stderr, "\007usq2: %s is not a SQueezed file\n", src_name);
fclose(in);
return(ERROR);
}
filecrc = (UNSIGNED) portgetw(in); /* checksum */
numnodes = portgetw(in);
if(numnodes < 0 || numnodes >= NUMVALS)
{
fprintf(stderr, "\007usq2: %s has invalid decode tree\n", src_name);
fclose(in);
return(ERROR);
}
/* Initialize for possible empty tree (SPEOF only) */
Dnode[0]._children[0] = -(SPEOF + 1);
Dnode[0]._children[1] = -(SPEOF + 1);
/* Get decoding tree from file */
for(i = 0; i < numnodes; ++i)
{
Dnode[i]._children[0] = portgetw(in);
Dnode[i]._children[1] = portgetw(in);
}
/* now make target filename */
strcpy(origname,tgt_path);
strcat(origname,next);
/* Get translated output bytes and write file */
if (!Inbackground)
fprintf(stderr, "usq2: %s -> %s\n",src_name,origname);
if((out=fopen(origname, "wb"))==NULL)
{
fprintf(stderr, "\007usq2: can't create %s\n", origname);
fclose(in);
return(ERROR);
}
/* decode file */
while ((c = getcr()) != EOF)
{
crc += (UNSIGNED) c;
if(fputc(c,out)!=c)
{
fclose(in);
fclose(out);
#ifdef MSDMSC
fprintf(stderr,"\007usq2: error in writing file: %s\n",origname);
exit(1);
#else
abort("\007usq2: error in writing file: %s\n",origname);
#endif
}
}
fclose(in);
if(fflush(out)<0 || ferror(out)<0)
abort("\007usq2: Error writing file: %s\n",origname);
if(fclose(out)<0)
abort("\007usq2: Error closing file: %s\n",origname);
if( crc != filecrc )
{
fprintf(stderr, "\007usq2: bad checksum in %s\n", src_name);
fflush(stdout);
return(ERROR);
}
return(OK);
}
/*** from utr.c - */
/* initialize decoding functions */
init_cr()
{
Repct = 0;
}
init_huff()
{
Bpos = 99; /* force initial read */
}
/* Get bytes with decoding - this decodes repetition,
* calls getuhuff to decode file stream into byte
* level code with only repetition encoding.
*
* The code is simple passing through of bytes except
* that DLE is encoded as DLE-zero and other values
* repeated more than twice are encoded as value-DLE-count.
*/
INT getcr()
{
register INT c;
if(Repct > 0)
{
/* Expanding a repeated char */
--Repct;
return(Value);
}
else
{
/* Nothing unusual */
if((c = getuhuff()) != DLE)
{
/* It's not the special delimiter */
Value = c;
if(Value == EOF)
Repct = LARGE;
return(Value);
}
else
{
/* Special token */
if((Repct = getuhuff()) == 0)
/* DLE, zero represents DLE */
return(DLE);
else
{
/* Begin expanding repetition */
Repct -= 2; /* 2nd time */
return(Value);
}
}
}
}
/* Decode file stream into a byte level code with only
* repetition encoding remaining.
*/
INT
getuhuff()
{
register INT i;
/* Follow bit stream in tree to a leaf*/
i = 0; /* Start at root of tree */
do
{
if(++Bpos > 7)
{
if((Curin = getc(in)) == ERROR)
{
if(sqid.sq_fflag == SPAN_CHR)
{
new_disk();
Curin = getc(in);
}
else
return(ERROR);
}
Bpos = 0;
/* move a level deeper in tree */
i = Dnode[i]._children[1 & Curin];
}
else
i = Dnode[i]._children[1 & (Curin >>= 1)];
} while(i >= 0);
/* Decode fake node index to original data value */
i = -(i + 1);
/* Decode special endfile token to normal EOF */
i = (i == SPEOF) ? EOF : i;
return(i);
}
/*
* Machine independent getw which always gets bytes in the same order
* as the CP/M version of SQ wrote them
*/
INT
portgetw(f)
FILE *f;
{
register INT c, result;
if((c = getc(f)) == EOF)
{
new_disk();
c = getc(f);
}
result = c & 0377;
if((c = getc(f)) == EOF)
{
new_disk();
c = getc(f);
}
result |= (c << 8);
return(result);
}
/* make string s lower case */
uncaps(s)
unsigned char *s;
{
for( ; *s; ++s)
if(isupper(*s))
*s = tolower(*s);
}
/*
* IsAnyLower returns TRUE if string s has lower case letters.
*/
IsAnyLower(s)
unsigned char *s;
{
for( ; *s; ++s)
if (islower(*s))
return(TRUE);
return(FALSE);
}
usage()
{
fprintf(stderr,"\n\nFile unsqueezer version %s by\n\n\tRichard Greenlaw\n\t251 Colony Ct.\n\tGahanna, Ohio 43230\n", VERSION);
fprintf(stderr,"\n\tMulti-disk version by Ark Software for the Public Domain");
fprintf(stderr,"\n\t **this program is free and not for sale**\n\n");
fprintf(stderr,"Usage: usq2 <source drive> <target files>\n\n");
fprintf(stderr,"\tie. usq2 a: c:\\subdir\\*.*\n\n");
exit(1);
}
hasbad(trg)
char *trg;
{
char c;
while (c = *trg++)
if (c == '*' || c == '?' || c == '.' || c == '\\' || c == '/')
return TRUE;
return FALSE;
}
haswild(trg)
char *trg;
{
if(strchr(trg,'?') != NULL || strchr(trg,'*') != NULL)
return TRUE;
else
return FALSE;
}
get_path(src, tgt)
char *src, *tgt;
{
char *d_ptr;
strcpy(tgt, src);
/* remove file name */
if((d_ptr = strrchr(tgt,'\\')) != NULL)
*++d_ptr = '\0';
else if((d_ptr = strrchr(tgt, '/')) != NULL)
*++d_ptr = '\0';
else if((d_ptr = strrchr(tgt, ':')) != NULL)
*++d_ptr = '\0';
else
#ifdef CPMC86
*tgt = '\0';
#else
strcpy(tgt, "\\");
#endif
}
/* read "RESTORE" header */
get_sqhdr()
{
long fseek();
fseek(in,0L,0);
return(fread(&sqid,sizeof(sqid),1,in));
}
/* mak_path() - make subdir(s) if neccesary */
#ifdef CPMC86
mak_path(org_name)
char *org_name;
{
return(0);
}
#else
mak_path(org_name)
char *org_name;
{
char fil_nam[PATHLEN+2];
char *fst, *beg_pos, *end_pos;
strcpy(fil_nam, org_name);
beg_pos = strchr(fil_nam, '\\');
while(beg_pos != NULL)
{
if((end_pos = strchr(beg_pos + 1, '\\')) != NULL)
{
*end_pos = '\0';
if((fst = filedir(fil_nam,0x10)) == NULL)
{
if(mkdir(fil_nam) == EOF)
return(EOF);
else
;
}
else
{
free(fst);
}
*end_pos = '\\';
}
beg_pos = end_pos;
}
return(0);
}
#endif
/* get file directory
*/
#ifdef MSDMSC
unsigned char *malloc();
unsigned char *realloc();
struct ff_str {
char dummy[21]; /* reserved for dos */
unsigned char attribute; /* returned attribute */
unsigned time;
unsigned date;
long size; /* size of file */
unsigned char fn[13]; /* string containing the filename */
};
char *filedir(filename,mode)
unsigned char *filename;
unsigned mode;
{
union REGS srvi, srvo;
struct SREGS segregs;
unsigned int ds, dx;
struct ff_str ff_area;
unsigned char *result;
int reslen=0;
#ifdef M_I86LM /* large model ? */
ds = FP_SEG(filename);
dx = FP_OFF(filename);
#else
segread(&segregs); /* get ds value */
dx = (unsigned) filename;
ds = segregs.ds;
#endif
srvi.x.dx = (unsigned int) &ff_area; /* set DTA */
srvi.h.ah = 0x1a;
intdosx(&srvi, &srvo, &segregs);
srvi.x.cx = mode; /* set search modes */
srvi.h.ah = 0x4e; /* find first */
srvi.x.dx = dx;
segregs.ds = ds;
intdosx(&srvi, &srvo, &segregs);
if(srvo.x.cflag)
return(NULL);
if((result = malloc(strlen(ff_area.fn) + 1)) == NULL)
return(result);
reslen = strlen(ff_area.fn) + 1;
strcpy(result, ff_area.fn);
srvi.h.ah = 0x4f; /* find next */
for(;;)
{
segregs.ds = ds;
intdosx(&srvi, &srvo, &segregs);
if(srvo.x.cflag)
{
result = realloc(result, reslen + 1);
if(result != NULL)
*(result + reslen) = '\0';
return(result);
}
result=realloc(result,reslen+strlen(ff_area.fn)+1);
if(result==NULL)
return NULL; /* no memory left */
strcpy(result+reslen,ff_area.fn);
reslen += (strlen(ff_area.fn) + 1);
}
}
#endif
#ifdef CPMC86
unsigned char *malloc();
unsigned char *realloc();
char *filedir(filename,mode)
unsigned char *filename;
int mode;
{
char fcb[36];
char tmpfile[30];
char dma[128];
struct { unsigned int ax,bx,cx,dx,si,di,ds,es;} srvi, srvo;
struct { unsigned int scs, sss, sds, ses;} segs;
unsigned int dataseg, fcboff;
unsigned char *result;
int reslen;
int i;
reslen = 0;
segread(&segs); /* get ds value */
fcboff = (unsigned) &fcb[0]; /* get fcb offset */
dataseg = segs.sds;
srvi.dx = (unsigned int) &dma[0]; /* set DMA */
srvi.cx = 0x001a; /* set offset */
sysint(224, &srvi, &srvo);
srvi.dx = dataseg;
srvi.cx = 0x0033; /* set segment */
sysint(224, &srvi, &srvo);
srvi.cx = 0x0011; /* find first */
srvi.dx = fcboff;
srvi.ds = dataseg;
if(!setfcb(fcb, filename))
{
return(NULL);
}
sysint(224, &srvi, &srvo);
if((srvo.ax & 0x00ff) == 255)
{
return(NULL);
}
hackname(tmpfile, dma + (srvo.ax * 32));
if((result = malloc(strlen(tmpfile) + 1)) == NULL)
return(result);
reslen = strlen(tmpfile) + 1;
strcpy(result, tmpfile);
srvi.cx = 0x0012; /* find next */
for(;;)
{
sysint(224, &srvi, &srvo);
if(srvo.ax == 255)
{
result = realloc(result, reslen + 1);
if(result != NULL)
*(result + reslen) = '\0';
return(result);
}
hackname(tmpfile, dma + (srvo.ax * 32));
result=realloc(result,reslen+strlen(tmpfile)+1);
if(result==NULL)
return NULL; /* no memory left */
strcpy(result+reslen,tmpfile);
reslen += (strlen(tmpfile) + 1);
}
}
hackname(dest,source)
char *dest, *source;
{
int i,j;
j = 0;
for (i = 1; i < 9; i++)
{
if (source[i] == ' ') break;
dest[j++] = source[i];
}
if (source[9] != ' ')
dest[j++] = '.';
for (i = 9; i < 12; i++)
{
if (source[i] == ' ') break;
dest[j++] = source[i];
}
dest[j] = '\0';
return dest;
}
setfcb(fcb,fname)
char *fcb, *fname;
{
char *fcb_ptr, *makefcb();
int i;
int qflg =0;
if((fcb_ptr = makefcb(fname)) == NULL)
return(0);
movmem(fcb_ptr, fcb, 36);
free(fcb_ptr);
for(i=1; i<12;i++)
{
if(fcb[i] == '*')
{
qflg = 1;
fcb[i] = '?';
continue;
}
if(qflg)
{
if(fcb[i] != ' ')
{
qflg =0;
continue;
}
fcb[i] = '?';
}
}
return(1);
}
#endif
#ifdef CPMC86
dsk_reset(drv) /* oh how I love CP/M!! */
char *drv;
{
struct { unsigned int ax,bx,cx,dx,si,di,ds,es;} srvi, srvo;
unsigned int vector;
int drvno;
drvno = toupper(*drv) - 65;
vector = 0x0001;
if(drvno != 0)
vector <<= drvno;
srvi.dx = vector;
srvi.cx = 0x0025; /* disk reset fn */
sysint(224, &srvi, &srvo);
return(srvo.ax);
}
#else
dsk_reset(drv)
char *drv;
{
return(0);
}
#endif
#ifdef MSDMSC
abort(string)
char *string;
{
fprintf(stderr,"\n\n%s\n\n", string);
exit(1);
}
#endif